package com.penghaonan.appframework.utils;

import java.lang.ref.SoftReference;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class WeakObservableList<T> implements IListenerList<T> {
    private final List<CustomReference<T>> observerList = new LinkedList<>();

    /**
     * 注册监听
     */
    public boolean addListener(T listener) {
        final boolean[] needAdd = {true};
        iterate(new OnIterator<T>() {

            @Override
            protected boolean onIterator(T item) {
                if (listener == item) {
                    needAdd[0] = false;
                    return true;
                }
                return false;
            }

            @Override
            protected void onFinish() {
                if (needAdd[0]) {
                    synchronized (WeakObservableList.this) {
                        observerList.add(new CustomReference<T>(listener));
                    }
                }
            }
        });
        return needAdd[0];
    }

    /**
     * 移除监听
     */
    public void removeListener(T listener) {
        iterate(new OnIterator<T>() {
            @Override
            protected boolean onIterator(T item) {
                if (listener == item) {
                    synchronized (WeakObservableList.this) {
                        remove();
                    }
                    return true;
                }
                return false;
            }
        });
    }

    /**
     * 遍历回调
     */
    public static abstract class OnIterator<T> {
        Iterator<CustomReference<T>> iterator;
        WeakObservableList<T> originalList;
        T currentItem;
        CustomReference<T> currentItemRef;

        void preStart(WeakObservableList<T> list) {
            originalList = list;
        }

        protected void onStart() {
        }

        boolean dispatchIterator(CustomReference<T> itemRef, T item) {
            currentItemRef = itemRef;
            currentItem = item;
            return onIterator(item);
        }

        /**
         * return true 终止循环
         */
        protected abstract boolean onIterator(T item);

        protected void onFinish() {
        }

        protected void remove() {
            if (currentItemRef != null && originalList != null) {
                originalList.observerList.remove(currentItemRef);
            }
        }
    }

    /**
     * 遍历器，过滤被回收的部分
     */
    public void iterate(OnIterator<T> onIterator) {
        List<CustomReference<T>> tmp = new LinkedList<>(observerList);
        Iterator<CustomReference<T>> iterator = tmp.iterator();
        onIterator.iterator = iterator;
        onIterator.preStart(this);
        onIterator.onStart();
        while (iterator.hasNext()) {
            CustomReference<T> reference = iterator.next();
            T keptObj = (T) reference.get();
            if (reference.get() == null || keptObj == null) {
                synchronized (this) {
                    observerList.remove(reference);
                }
            } else {
                boolean res = onIterator.dispatchIterator(reference, keptObj);
                if (res) {
                    break;
                }
            }
        }
        onIterator.onFinish();
    }

    public void clear() {
        observerList.clear();
    }

    public int observerCount() {
        return observerList.size();
    }

    private static class CustomReference<T> extends SoftReference<T> {

        public CustomReference(T referent) {
            super(referent);
        }

        @Override
        public T get() {
            return (T) super.get();
        }
    }
}
